﻿using System;
using System.Web;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Payroll.BusinessLogic.Caching;
using Payroll.BusinessLogic.Configuration.Settings;
using Payroll.BusinessLogic.Data;
using Payroll.BusinessLogic.Infrastructure;
using Payroll.Common.Utils;
using Payroll.Common;
using System.Web.Security;
using System.Security.Cryptography;
using Payroll.BusinessLogic.Localization;
namespace Payroll.BusinessLogic.EmployeeManagement
{
    public partial class EmployeeService : IEmployeeService
    {
        #region Fields

        /// <summary>
        /// Object context
        /// </summary>
        private readonly PayrollHRDataContext m_context;

        /// <summary>
        /// Cache manager
        /// </summary>
        private readonly ICacheManager _cacheManager;


        #endregion
        #region Ctor

        /// <summary>
        /// Ctor
        /// </summary>
        /// <param name="context">Object context</param>
        public EmployeeService(PayrollHRDataContext context)
        {
            this.m_context = context;
            this._cacheManager = new PayrollRequestCache();
        }

        #endregion
        /// <summary>
        /// Creates a password hash
        /// </summary>
        /// <param name="password">Password</param>
        /// <param name="salt">Salt</param>
        /// <returns>Password hash</returns>
        private string CreatePasswordHash(string password, string salt = "")
        {
            //MD5, SHA1
            string passwordFormat = IoC.Resolve<ISettingManager>().GetSettingValue("Security.PasswordFormat");
            if (String.IsNullOrEmpty(passwordFormat))
                passwordFormat = "SHA1";
            
            return FormsAuthentication.HashPasswordForStoringInConfigFile(password + salt, passwordFormat);
        }
        /// <summary>
        /// Creates a salt
        /// </summary>
        /// <param name="size">A salt size</param>
        /// <returns>A salt</returns>
        private string CreateSalt(int size)
        {
            var provider = new RNGCryptoServiceProvider();
            byte[] data = new byte[size];
            provider.GetBytes(data);
            return Convert.ToBase64String(data);
        }
        public Employee SetEmail(int employeeId, string newEmail)
        {
            throw new NotImplementedException();
        }

        public Employee ChangeEmployeeUsername(int employeeId, string newUsername)
        {
            throw new NotImplementedException();
        }

        public void CreateAnonymousUser()
        {
            throw new NotImplementedException();
        }

        public void ApplyGiftCardCouponCode(string couponCodesXml)
        {
            throw new NotImplementedException();
        }

        public PagedList<Employee> GetAllEmployee()
        {
            return GetAllEmployee(Name: null, username: string.Empty, pageIndex: 0, pageSize: int.MaxValue);
        }
        public PagedList<Employee> GetAllEmployeeByFilter(int? employeeId, string employeeName = null, string StoreId = null, string PositionId = null,
            string Startingdate = null, string SignedDate = null, string ResignDate = null, bool isDelete = false,
            int pageSize = int.MaxValue, int pageIndex = 0)
        {
            return null;
        }
        public PagedList<Employee> GetAllEmployee(string Name, string username, int pageSize, int pageIndex)
        {
            if (Name == null)
                Name = string.Empty;
            if (username == null)
                username = string.Empty;
            var query = from e in m_context.Employees
                        where (e.Username.Contains(username) || username == null || username == "")
                        && (e.Name.Contains(Name) || Name == null || Name == "") && e.Deleted == true
                        select new Employee
                        {
                            EmployeeId = e.EmployeeId,
                            Name = e.Name,
                            Mobile = e.Mobile,
                            CreatedByID = e.CreatedByID,
                            UpdateByID = e.UpdateByID,
                            CreatedOn = e.CreatedOn,
                            UpdatedOn = e.UpdatedOn,
                            EmailAddress = e.EmailAddress,
                            Username = e.Username,
                            Active = e.Active
                        };
            return new PagedList<Employee>(query, pageIndex, pageSize);
        }

        public List<Employee> GetEmployeeByEmployeeRoleId(int storeId, int PositionId, string employeeCode, string employeeName, int UserId, int pageSize = int.MaxValue, int pageIndex = 0)
        {
            return null;
        }

        public Employee GetEmployeeByEmail(string email)
        {
            return null;
        }

        public Employee GetEmployeeByUsername(string username)
        {
            if (string.IsNullOrEmpty(username))
                return null;

            var query = from c in m_context.Employees
                        where c.Username == username && c.Deleted == true
                        select new Employee
                        {
                            EmployeeId = c.EmployeeId,
                            Name = c.Name,
                            Mobile = c.Mobile,
                            PasswordHash = c.PasswordHash,
                            EmailAddress = c.EmailAddress,
                            Phone = c.Phone,
                            Active = c.Active,
                            IsAdmin = c.IsAdmin
                        };
            return query.FirstOrDefault();
        }

        public void SaveEmployee(Employee employee)
        {
            if (CommonHelper.IsBlank(employee.Username))
            {
                throw new ArgumentNullException("Username is not blank.");
            }
            var item = (from e in m_context.Employees
                        where e.Username == employee.Username && e.Deleted == true
                        select e).FirstOrDefault();
            if (!CommonHelper.IsNull(item))
            {
                throw new ArgumentNullException("Username exists.");
            }
            item = new BusinessLogic.Data.Employee
            {
                EmployeeId = employee.EmployeeId,
                Name = employee.Name,
                Mobile = employee.Mobile,
                Username = employee.Username,
                PasswordHash = this.CreatePasswordHash(employee.PasswordHash.ToUpper()),
                EmailAddress = employee.EmailAddress,
                Phone = employee.Phone,
                Active = employee.Active,
                IsAdmin = employee.IsAdmin,
                CreatedByID = 2,// PayrollContext.Current.User.EmployeeId,
                UpdateByID = 2,//PayrollContext.Current.User.EmployeeId,
                CreatedOn = DateTime.Now,
                UpdatedOn = DateTime.Now,
                Deleted = true
            };
            m_context.Employees.InsertOnSubmit(item);
            m_context.SubmitChanges();
        }
        public int SaveEmployeePemision(Employee employee)
        {
            if (CommonHelper.IsBlank(employee.Username))
            {
                throw new ArgumentNullException("Username is not blank.");
            }
            var item = (from e in m_context.Employees
                        where e.Username == employee.Username && e.Deleted == true
                        select e).FirstOrDefault();
            if (!CommonHelper.IsNull(item))
            {
                throw new ArgumentNullException("Username exists.");
            }
            item = new BusinessLogic.Data.Employee
            {
                EmployeeId = employee.EmployeeId,
                Name = employee.Name,
                Mobile = employee.Mobile,
                Username = employee.Username,
                PasswordHash = this.CreatePasswordHash(employee.PasswordHash.ToUpper()),
                EmailAddress = employee.EmailAddress,
                Phone = employee.Phone,
                Active = employee.Active,
                IsAdmin = employee.IsAdmin,
                CreatedByID = 2,// PayrollContext.Current.User.EmployeeId,
                UpdateByID = 2,//PayrollContext.Current.User.EmployeeId,
                CreatedOn = DateTime.Now,
                UpdatedOn = DateTime.Now,
                Deleted = true
            };
            m_context.Employees.InsertOnSubmit(item);
            m_context.SubmitChanges();
            return item.EmployeeId;
        }
        public void SaveEployeeStore(int employeeId, int StoreId, string Effectivedate)
        {

        }
        public void SavePosition(int employeeId, int PositionId, string Effectivedate)
        {

        }
        public void SaveSalary(int employeeId, int salaryTypeId, string Effectivedate, decimal salary)
        {

        }
        public void UpdateEmployee(Employee employee)
        {
            var item = m_context.Employees.SingleOrDefault(e => e.EmployeeId == employee.EmployeeId);
            if (!CommonHelper.IsNull(item))
            {
                if (!item.Username.Equals(employee.Username))
                {
                    var query = m_context.Employees.Where(e => e.Username == employee.Username).ToList();
                    if (query.Count > 0)
                    {
                        throw new ArgumentNullException("Username exists.");
                    }
                }
                item.EmployeeId = employee.EmployeeId;
                item.Name = employee.Name;
                item.Mobile = employee.Mobile;
                item.EmailAddress = employee.EmailAddress;
                item.Phone = employee.Phone;
                item.Active = employee.Active;
                //tam khoa
                //item.UpdateByID = PayrollContext.Current.User.EmployeeId;
                item.UpdatedOn = DateTime.Now;
                item.Deleted = true;
                m_context.SubmitChanges();
            }
        }
        private void SavePermision(List<Permision> List, int EmployeeId)
        {
            var query = m_context.Permisions.Where(p => p.EmployeeId == EmployeeId);
            m_context.Permisions.DeleteAllOnSubmit(query);
            m_context.SubmitChanges();

            List.ForEach(p => p.EmployeeId = EmployeeId);
            m_context.Permisions.InsertAllOnSubmit(List);
            m_context.SubmitChanges();
        }
        public void ModifyPassword(string email, string oldPassword, string password)
        {
            var employee = GetEmployeeByUsername(email);
            if (employee != null)
            {
                //string oldPasswordHash = CreatePasswordHash(oldPassword, "");
                //if (!employee.PasswordHash.Equals(oldPasswordHash))
                //    throw new PayrollException("Current Password doesn't match.");

                ModifyPassword(employee.EmployeeId, password);
            }
        }

        public void ModifyPassword(string email, string newPassword)
        {
            if (String.IsNullOrWhiteSpace(newPassword))
                throw new PayrollException(IoC.Resolve<ILocalizationManager>().GetLocaleResourceString("Customer.PasswordIsRequired"));
            newPassword = newPassword.Trim();
            throw new NotImplementedException();
        }

        public void ModifyPassword(int employeeId, string newPassword)
        {
            var item = m_context.Employees.SingleOrDefault(e => e.EmployeeId == employeeId);
            if (!CommonHelper.IsNull(item))
            {
                item.PasswordHash = this.CreatePasswordHash(newPassword.ToUpper());
                m_context.SubmitChanges();
            }
        }

        public void Activate(int employeerId)
        {
            Activate(employeerId, false);
        }

        public void Activate(int employeeId, bool sendemployeeWelcomeMessage)
        {
            var item = m_context.Employees.SingleOrDefault(e => e.EmployeeId == employeeId);
            if (!CommonHelper.IsNull(item))
            {
                item.Active = true;
                m_context.SubmitChanges();
                if (sendemployeeWelcomeMessage)
                {
                    //IoC.Resolve<IMessageService>().SendCustomerWelcomeMessage(customer, NopContext.Current.WorkingLanguage.LanguageId);
                }
            }
        }

        public void Deactivate(int employeeId)
        {
            var item = m_context.Employees.SingleOrDefault(e => e.EmployeeId == employeeId);
            if (!CommonHelper.IsNull(item))
            {
                item.Active = false;
                m_context.SubmitChanges();
            }
        }

        public bool Login(string Username, string password)
        {
            if (Username == null)
                Username = string.Empty;
            Username = Username.Trim();

            var employee = GetEmployeeByUsername(Username);

            if (employee == null)
                return false;

            if (!employee.Active)
                return false;

            if (employee.Deleted)
                return false;
            string passwordHash = CreatePasswordHash(password.ToUpper());

            bool result = employee.PasswordHash.Equals(passwordHash);
            if (result)
            {
                var registeredEmployeeSession = GetEmployeeSessionByEmployeeId(employee.EmployeeId);
                if (registeredEmployeeSession != null)
                {
                    registeredEmployeeSession.IsExpired = false;
                    PayrollContext.Current.Session = registeredEmployeeSession;
                }
            }
            if (PayrollContext.Current.Session == null)
                PayrollContext.Current.Session = PayrollContext.Current.GetSession(true);
            PayrollContext.Current.Session.IsExpired = false;
            PayrollContext.Current.Session.LastAccessed = DateTime.UtcNow;
            PayrollContext.Current.Session.EmployeeId = employee.EmployeeId;
            return result;
        }

        public void Logout()
        {
            if (PayrollContext.Current != null)
            {
                PayrollContext.Current.ResetSession();
            }
            //if (PayrollContext.Current != null &&
            //    PayrollContext.Current.IsCurrentCustomerImpersonated &&
            //    PayrollContext.Current.OriginalUser != null)
            //{
            //    PayrollContext.Current.OriginalUser.ImpersonatedCustomerGuid = Guid.Empty;
            //}
            if (HttpContext.Current != null && HttpContext.Current.Session != null)
            {
                HttpContext.Current.Session.Abandon();
            }
            FormsAuthentication.SignOut();
        }

        public EmployeeSession GetEmployeeSessionByGuid(Guid employeeSessionGuid)
        {
            if (employeeSessionGuid == Guid.Empty)
                return null;


            var query = from cs in m_context.EmployeeSessions
                        where cs.EmployeeSessionGuid == employeeSessionGuid
                        orderby cs.LastAccessed descending
                        select new EmployeeSession
                        {
                            EmployeeId = cs.EmployeeId,
                            EmployeeSessionGuid = cs.EmployeeSessionGuid,
                            IsExpired = cs.IsExpired,
                            LastAccessed = cs.LastAccessed
                        };
            var employeeSession = query.FirstOrDefault();
            return employeeSession;
        }

        public void DeleteEmployeeSession(Guid employeeSessionGuid)
        {
            throw new NotImplementedException();
        }

        public List<EmployeeSession> GetAllEmployeeSession()
        {
            throw new NotImplementedException();
        }

        public void DeleteExpiredEmployeeSession(DateTime olderThan)
        {
            throw new NotImplementedException();
        }

        public EmployeeSession SaveCustomerSession(Guid employeeSessionGuid, int employeeId, DateTime lastAccessed, bool isExpired)
        {
            var customerSession = (from es in m_context.EmployeeSessions
                                   where es.EmployeeSessionGuid == employeeSessionGuid
                                   select es).FirstOrDefault();
            if (customerSession == null)
            {
                customerSession = new BusinessLogic.Data.EmployeeSession()
                {
                    EmployeeSessionGuid = employeeSessionGuid,
                    EmployeeId = employeeId,
                    LastAccessed = lastAccessed,
                    IsExpired = isExpired
                };

                m_context.EmployeeSessions.InsertOnSubmit(customerSession);
                m_context.SubmitChanges();
            }
            else
            {
                customerSession.EmployeeSessionGuid = employeeSessionGuid;
                customerSession.EmployeeId = employeeId;
                customerSession.LastAccessed = lastAccessed;
                customerSession.IsExpired = isExpired;
                m_context.SubmitChanges();
            }
            return new EmployeeSession
            {
                EmployeeId = customerSession.EmployeeId,
                EmployeeSessionGuid = customerSession.EmployeeSessionGuid,
                LastAccessed = customerSession.LastAccessed,
                IsExpired = customerSession.IsExpired
            };
        }


        public Employee GetEmployeeById(int EmployeeId)
        {
            var query = from e in m_context.Employees
                        where e.EmployeeId == EmployeeId
                        orderby e.EmployeeId
                        select new Employee
                        {
                            EmployeeId = e.EmployeeId,
                            Name = e.Name,
                            Mobile = e.Mobile,
                            EmailAddress = e.EmailAddress,
                            Phone = e.Phone,
                            Username = e.Username,
                            Active = e.Active,
                            Deleted = e.Deleted,
                            CreatedByID = e.CreatedByID,
                            UpdateByID = e.UpdateByID,
                            CreatedOn = e.CreatedOn,
                            UpdatedOn = e.UpdatedOn
                        };
            return query.FirstOrDefault();
        }


        public EmployeeSession GetEmployeeByGuid(Guid customerSessionGuid)
        {
            if (customerSessionGuid == Guid.Empty)
                return null;


            var query = from cs in m_context.EmployeeSessions
                        where cs.EmployeeSessionGuid == customerSessionGuid
                        orderby cs.LastAccessed descending
                        select new EmployeeSession
                        {
                            EmployeeSessionGuid = cs.EmployeeSessionGuid,
                            EmployeeId = cs.EmployeeId,
                            IsExpired = cs.IsExpired,
                            LastAccessed = cs.LastAccessed
                        };
            var customerSession = query.FirstOrDefault();
            return customerSession;
        }


        public EmployeeSession GetEmployeeSessionByEmployeeId(int employeeId)
        {
            if (employeeId == 0)
                return null;

            //m_context.EmployeeSessions.DeleteAllOnSubmit(m_context.EmployeeSessions.Where(e => e.EmployeeSessionGuid == Guid.Empty));

            //m_context.SubmitChanges();
            var query = from cs in m_context.EmployeeSessions
                        where cs.EmployeeId == employeeId && cs.EmployeeSessionGuid != Guid.Empty
                        orderby cs.LastAccessed descending
                        select new EmployeeSession
                        {
                            EmployeeSessionGuid = cs.EmployeeSessionGuid,
                            EmployeeId = cs.EmployeeId,
                            IsExpired = cs.IsExpired,
                            LastAccessed = cs.LastAccessed
                        };
            var employeeSession = query.FirstOrDefault();
            return employeeSession;
        }


        public void UpdateDelete(int employeeId, bool status)
        {
            var item = (from e in m_context.Employees
                        where e.EmployeeId == employeeId
                        select e).FirstOrDefault();
            if (!CommonHelper.IsNull(item))
            {
                item.Deleted = status;
                m_context.SubmitChanges();
            }
        }


        public int SaveEmployee(Employee employee, List<Permision> List)
        {
            int employeeId = this.SaveEmployeePemision(employee);
            this.SavePermision(List, employeeId);
            return employeeId;
        }

        public int UpdateEmployee(Employee employee, List<Permision> List)
        {
            this.UpdateEmployee(employee);
            this.SavePermision(List, employee.EmployeeId);
            return employee.EmployeeId;
        }


        public List<Permision> GetPermisionById(int employeeid)
        {
            var query = (from p in m_context.Permisions
                         where p.EmployeeId == employeeid
                         select p);

            return query.ToList();
        }
    }
}
